using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public static class LevelPlayUtil
    {
        private static readonly IReadOnlyList<Vector3> fourElevatorFloorDirs = new List<Vector3>()
        {
            new Vector3(0, 0, 1),
            new Vector3(1, 0, 0),
            new Vector3(0, 0, -1),
            new Vector3(-1, 0, 0)
        };

        public static LevelRegionPackConfig GetRegionPackConfig()
        {
            var levelPlay = LevelPlayModule.Instance.levelPlay;
            if (levelPlay != null)
            {
                return levelPlay.regionCtrl.cfgRegionPack;
            }
            return null;
        }

        public static LevelCharacterEntity GetMainCharacter()
        {
            var levelPlay = LevelPlayModule.Instance.levelPlay;
            if (levelPlay != null)
            {
                return levelPlay.regionCtrl.entityCtrl.GetMainCharacter();
            }
            return null;
        }

        public static DynLevelPlayer GetDynLevelPlayer()
        {
            var levelPlay = LevelPlayModule.Instance.levelPlay;
            if (levelPlay != null)
            {
                return levelPlay.levelPlayer;
            }
            return null;
        }

        /// <summary>
        /// 根据地面MeshCollider校准实体高度后返回实体实际显示位置
        /// </summary>
        /// <param name="logicX">单位：厘米</param>
        /// <param name="logicY">单位：厘米</param>
        /// <param name="logicZ">单位：厘米</param>
        /// <param name="hitInfo"></param>
        /// <returns></returns>
        public static Vector3 GetAdjustedPosByGround(float logicX, float logicY, float logicZ)
        {
            float posX = logicX / GameGlobalConst.LogicPosScale;
            float posY = logicY / GameGlobalConst.LogicPosScale;
            float posZ = logicZ / GameGlobalConst.LogicPosScale;
            if (GameScenePlayUtil.TryGroundRaycast(posX, posY, posZ, out var hit))
            {
                return new Vector3(posX, hit.point.y, posZ);
            }
            else
            {
                return new Vector3(posX, posY, posZ);
            }
        }

        /// <summary>
        /// 加载单个region的配置
        /// </summary>
        /// <param name="cfgResloader"></param>
        /// <param name="cfgRegion"></param>
        /// <returns></returns>
        public static async UniTask<LevelRegionPackConfig> LoadRegionCfg(CfgRegionInstance cfgRegion, ResLoader customLoader = null)
        {
            var path = PathConstant.GetSceneGameplayCfg(cfgRegion.GameplayConfig);
            var gamePlayConfig = await GameplayAreaModularConfigMgr.Instance.LoadModularConfig<LevelGamePlayConfig>(path, customLoader);
            var cfgScene = TableCenter.scene.Get(cfgRegion.SceneId);
            var regionPack = new LevelRegionPackConfig()
            {
                gamePlayConfig = gamePlayConfig,
                cfgRegionInstance = cfgRegion,
                cfgScene = cfgScene,
            };
            return regionPack;
        }

        /// <summary>
        /// 创建电梯楼层围栏
        /// </summary>
        /// <param name="floorData"></param>
        /// <param name="elevatorRotation">电梯旋转，围栏随电梯旋转，电梯运动时不支持旋转，但因为围栏属于楼层，不能放到电梯实体上，所以需要专门传入</param>
        /// <returns></returns>
        public static GameObject GenElevatorFloorGO(ElevatorFloorData floorData, Quaternion elevatorRotation, string goName)
        {
#if UNITY_EDITOR
            //编辑器模式下一定创建对象（为了方便关卡编辑器调试）
            GameObject floorGo = new GameObject(goName);
#else
            //非编辑器模式下只在有至少一个围栏数据的情况下才创建对象
            GameObject floorGo = null;
#endif
            for (byte dirIndex = 0; dirIndex < 4; dirIndex++)
            {
                ushort intWidth = floorData.GetFenceWidth(dirIndex);
                if (intWidth > 0)
                {
                    floorGo ??= new GameObject(goName);
                    float width = (float)intWidth / GameGlobalConst.LogicPosScale;
                    float offsetLength = (float)floorData.GetFenceOffset(dirIndex) / GameGlobalConst.LogicPosScale;
                    Vector3 dir = fourElevatorFloorDirs[dirIndex];
                    BoxCollider collider = floorGo.AddComponent<BoxCollider>();
                    Vector3 offset = dir * offsetLength;
                    offset.y = LevelDataConsts.ElevatorFenceHeight * 0.5f;
                    collider.center = offset;
                    collider.size = new Vector3(dir.x == 0 ? width : 0.01f, LevelDataConsts.ElevatorFenceHeight, dir.z == 0 ? width : 0.01f);
                }
            }
            if (floorGo != null)
            {
                floorGo.transform.rotation = elevatorRotation;
                floorGo.transform.position = GameMathUtil.LogicPos2UnityPos(floorData.position);
            }
            return floorGo;
        }
    }
}
